
import { window } from "vscode";
import * as vscode from "vscode";
import { Lazy } from "../../../utils/lazy";
import TypeScriptServiceClientHost from "../../../typeScriptServiceClientHost";
import { isArray } from "util";
import { 格式化当前文档 as 格式化当前文档 } from "../ctsUtils/utils";
import { 增加的词典 } from "./externalDictEditCommand";

export class 整理外部词典文件_ {
    public static readonly ID = 'ctsscript.整理外部词典文件_';
    public readonly ID = 整理外部词典文件_.ID;

    constructor(
        private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>,
    ) { }
    public async execute() {
        vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: "正在整理..." }, () => this.执行());
    }
    public async 执行(){
        if (!window.activeTextEditor || !window.activeTextEditor.document) {
            vscode.window.showInformationMessage("dictconfig.json 文件必须为当前编辑器打开的文件。")
            return;
        }
        const 当前文档 = window.activeTextEditor!.document;
        const 英汉多译对象: 多译词典对象_ = new Map();
        const 通用词典对象: 通用词典对象_ = new Map();
        const 未译词典对象: 通用词典对象_ = new Map();
        const 汉英多译对象: 混合词典对象_ = new Map();
        const 规范化路径 = this.lazyClientHost.value.serviceClient.normalizedPath(当前文档.uri);
        if (规范化路径 && 规范化路径.endsWith("dictconfig.json")) {
            const { 未译词典, 汉英多译, 英汉多译, 通用词典 } = 填充初始化映射(JSON.parse(当前文档.getText()) as 词典文件_);
            if (未译词典) {
                未译词典.forEach((v, k) => {
                    加入通用词典对象(通用词典对象, k, v, 英汉多译对象, 未译词典对象);
                });
            }
            if (汉英多译) {
                汉英多译.forEach((v, k) => {
                    加入通用词典对象(通用词典对象, k, v, 英汉多译对象,未译词典对象);
                });
            }
            if (英汉多译) {
                英汉多译.forEach((v, k) => {
                    if (isArray(v)) {
                        if (v.length === 1) {
                            加入通用词典对象(通用词典对象, k, v[0], 英汉多译对象,未译词典对象);
                        }
                        else {
                            if (通用词典对象.has(k)) {
                                const 通用存在 = 通用词典对象.get(k)!;
                                v.push(通用存在);
                                通用词典对象.delete(k);
                            }
                            const 输出存在 = 英汉多译对象.get(k);
                            if (输出存在) {
                                加入如果唯一(输出存在, v)
                            }
                            else {
                                英汉多译对象.set(k, v);
                            }
                        }
                    }
                    else if (typeof v === "string") {
                        加入通用词典对象(通用词典对象, k, v, 英汉多译对象,未译词典对象);
                    }
                });
            }
            if (通用词典) {
                通用词典.forEach((v, k) => {
                    加入通用词典对象(通用词典对象, k, v, 英汉多译对象,未译词典对象);
                });
            }
            通用词典对象.forEach((v, k) => {
                if (汉英多译对象.has(v)) {
                    let 存在 = 汉英多译对象.get(v)!;
                    if (isArray(存在)) {
                        加入如果唯一(存在, k);
                        通用词典对象.delete(k);
                    }
                    else {
                        let 临时数组 = [存在]
                        if (加入如果唯一(临时数组, k)) {
                            汉英多译对象.set(v, 临时数组);
                            通用词典对象.delete(k);
                            通用词典对象.delete(存在);
                        };
                    }
                }
                else {
                    汉英多译对象.set(v, k);
                }
            });
            const 新文本 = 排序输出(汉英多译对象, 英汉多译对象, 未译词典对象, 通用词典对象);
            if (!新文本) {
                vscode.window.showErrorMessage<vscode.MessageItem>("整理失败", { title: "整理失败", isCloseAffordance: true });
            }
            await vscode.window.activeTextEditor!.edit(e => {
                e.replace(new vscode.Range(new vscode.Position(0, 0),
                    new vscode.Position(vscode.window.activeTextEditor!.document.lineCount - 1,
                        vscode.window.activeTextEditor!.document.lineAt(vscode.window.activeTextEditor!.document.lineCount - 1).text.length)),
                    新文本);
            });
            await 格式化当前文档();
            vscode.window.showInformationMessage("整理完成", { title: "整理完成", isCloseAffordance: true });
        }

    }
}

function arrayFrom<T>(iterator: Iterator<T> | IterableIterator<T>): T[] {
    const result: any[] = [];
    for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
        result.push(value);
    }
    return result;
}

function 排序输出(汉英多译数据: 混合词典对象_, 多译词典对象: 多译词典对象_, 未译词典对象: 通用词典对象_, 通用词典对象: 通用词典对象_): string {
    const 输出结果: 词典映射_ = {};
    if (汉英多译数据 && 汉英多译数据.size) {
        const keys = 汉英多译数据.keys();
        const keysSort = arrayFrom(keys).sort();
        for (let k of keysSort) {
            let v = 汉英多译数据.get(k);
            if (isArray(v)) {
                (输出结果.汉英多译 || (输出结果.汉英多译 = new Map()))!.set(k, v);
            }
        }
    }

    if (多译词典对象 && 多译词典对象.size) {
        const keys = 多译词典对象.keys();
        const keysSort = arrayFrom(keys).sort();
        const 输出: 多译词典对象_ = new Map();
        for (let k of keysSort) {
            输出.set(k, 多译词典对象.get(k)!);
        }
        输出结果.英汉多译 = 输出;
    }

    let 未译词典 = "";
    if (未译词典对象 && 未译词典对象.size) {
        const 临时: string[] = [];
        const keys = 未译词典对象.keys();
        const keysSort = arrayFrom(keys).sort();
        const 输出: 通用词典对象_ = new Map();
        for (let k of keysSort) {
            输出.set(k, 未译词典对象.get(k)!);
        }
        输出.forEach((v, k) => {
            临时.push(`"${k}":"${v}"`);
        });
        未译词典 = `"未译词典":{${临时.join(",")}}`;
    }

    let 通用词典 = "";
    if (通用词典对象 && 通用词典对象.size) {
        const 临时: string[] = [];
        const keys = 通用词典对象.keys();
        const keysSort = arrayFrom(keys).sort();
        const 输出: 通用词典对象_ = new Map();
        for (let k of keysSort) {
            输出.set(k, 通用词典对象.get(k)!);
        }
        输出.forEach((v, k) => {
            临时.push(`"${k}":"${v}"`);
        });
        通用词典 = `"通用词典":{${临时.join(",")}}`;
    }

    let 英汉多译 = "";
    if (输出结果.英汉多译) {
        const 临时: string[] = [];
        输出结果.英汉多译.forEach((v, k) => {
            if (isArray(v)) {
                for (let vv of v) {
                    临时.push(`"${k}":"${vv}"`);
                }
            }
        });
        英汉多译 = `"英汉多译":{${临时.join(",")}}`;
    }

    let 汉英多译 = "";
    if (输出结果.汉英多译) {
        const 临时: string[] = [];
        输出结果.汉英多译.forEach((v, k) => {
            if (isArray(v)) {
                for (let vv of v) {
                    临时.push(`"${vv}":"${k}"`);
                }
            }
        });
        汉英多译 = `"汉英多译":{${临时.join(",")}}`;
    }

    const 输出数组: string[] = [];
    if (未译词典) {
        输出数组.push(未译词典);
    }
    if (通用词典) {
        输出数组.push(通用词典);
    }
    if (英汉多译) {
        输出数组.push(英汉多译);
    }
    if (汉英多译) {
        输出数组.push(汉英多译);
    }
    if (输出数组.length) {
        return `{${输出数组.join(",")}}`;
    }
    return "";
}

function 加入通用词典对象(通用词典对象: Map<string, string>, k: string, v: string, 多译词典对象: Map<string, string[]>, 未译词典对象: Map<string, string>) {
    if (k === v) {
        未译词典对象.set(k, v);
        return;
    }
    if (通用词典对象.has(k)) {
        const 存在 = 通用词典对象.get(k)!;
        if (存在 !== v) {
            const 输出存在 = 多译词典对象.get(k);
            if (输出存在) {
                加入如果唯一(输出存在, [存在, v]);
            }
            else {
                多译词典对象.set(k, [存在, v]);
            }
            通用词典对象.delete(k);
        }
    }
    else {
        通用词典对象.set(k, v);
    }
}

function 加入如果唯一<T>(数组: T[], 元素: T | T[]) {
    if (!数组) {
        数组 = [];
    }
    if (isArray(元素)) {
        元素.forEach(v => {
            加入如果唯一(数组, v)
        })
    }
    else {
        let 不加入 = false;
        for (let i = 0; i < 数组.length; i++) {
            if (数组[i] === 元素) {
                不加入 = true;
                break;
            }
        }
        if (!不加入) {
            数组.push(元素);
            return true;
        }
    }
    return false;
}

function 填充初始化映射(结构化文档: 词典文件_): 词典映射_ {
    let 未译词典!: Map<string, string>;
    let 汉英多译!: Map<string, string>;
    let 英汉多译!: Map<string, string[]>;
    let 通用词典: Map<string, string> = 增加的词典;
    if (结构化文档) {
        if (结构化文档.未译词典) {
            for (let k in 结构化文档.未译词典) {
                if (有属性(结构化文档.未译词典, k)) {
                    (未译词典 || (未译词典 = new Map<string, string>())).set(k, 结构化文档.未译词典[k]);
                }
            }
        }
        if (结构化文档.汉英多译) {
            for (let k in 结构化文档.汉英多译) {
                if (有属性(结构化文档.汉英多译, k)) {
                    (汉英多译 || (汉英多译 = new Map<string, string>())).set(k, 结构化文档.汉英多译[k]);
                }
            }
        }
        if (结构化文档.英汉多译) {
            for (let k in 结构化文档.英汉多译) {
                if (有属性(结构化文档.英汉多译, k)) {
                    (英汉多译 || (英汉多译 = new Map<string, string[]>())).set(k, 结构化文档.英汉多译![k]);
                }
            }
        }
        if (结构化文档.通用词典) {
            for (let k in 结构化文档.通用词典) {
                if (有属性(结构化文档.通用词典, k)) {
                    (通用词典 || (通用词典 = new Map<string, string>())).set(k, 结构化文档!.通用词典![k]);
                }
            }
        }
    }
    return { 通用词典, 英汉多译, 汉英多译, 未译词典 };
}

function 有属性<T>(本体对象: T, k: string): boolean {
    return Object.prototype.hasOwnProperty.call(本体对象, k)
}

type 词典文件_ = {
    通用词典?: 原始通用词典对象_;
    未译词典?: 原始通用词典对象_;
    英汉多译?: 原始多译词典对象_;
    汉英多译?: 原始通用词典对象_;
}

type 词典映射_ = {
    通用词典?: 通用词典对象_;
    未译词典?: 通用词典对象_;
    英汉多译?: 多译词典对象_;
    汉英多译?: 通用词典对象_;
}

type 原始通用词典对象_ = {
    [index: string]: string;
}

type 原始多译词典对象_ = {
    [index: string]: string[];
}

type 多译词典对象_ = Map<string, string[]>;
type 通用词典对象_ = Map<string, string>;
type 混合词典对象_ = Map<string, string | string[]>;